package com.djf.djfword.service;

import com.djf.djfword.entity.ContractData;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Word模板处理服务类
 * 专门用于处理从现有Word模板读取并填充数据
 * 
 * @author djf
 */
@Service
public class TemplateWordService {
    
    @Autowired
    private ContractDataService contractDataService;

    /**
     * 从模板文件读取并填充数据
     * @param templatePath 模板文件路径
     * @param data 要填充的数据
     * @param response HTTP响应对象
     * @param outputFileName 输出文件名
     * @throws IOException IO异常
     */
    public void fillTemplateAndExport(String templatePath, Map<String, String> data, 
                                     HttpServletResponse response, String outputFileName) throws IOException {
        // 读取模板文件
        File templateFile = new File(templatePath);
        if (!templateFile.exists()) {
            throw new FileNotFoundException("模板文件不存在: " + templatePath);
        }
        
        // 加载Word文档
        FileInputStream fis = new FileInputStream(templateFile);
        XWPFDocument document = new XWPFDocument(fis);
        
        // 替换段落中的占位符
        replacePlaceholdersInParagraphs(document, data);
        
        // 替换表格中的占位符
        replacePlaceholdersInTables(document, data);
        
        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.setHeader("Content-Disposition", "attachment; filename=" + outputFileName);
        
        // 写入响应流
        document.write(response.getOutputStream());
        
        // 关闭资源
        document.close();
        fis.close();
    }
    
    /**
     * 从模板文件填充数据并导出
     * 
     * @param templateFile 模板文件
     * @param data 要填充的数据
     * @param response HTTP响应
     * @throws IOException IO异常
     */
    public void fillTemplateAndExport(MultipartFile templateFile, Map<String, String> data, 
                                     HttpServletResponse response) throws IOException {
        
        // 读取模板文件
        XWPFDocument document = new XWPFDocument(templateFile.getInputStream());
        
        // 替换文档中的占位符
        replaceTextInDocument(document, data);
        
        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.setHeader("Content-Disposition", "attachment; filename=filled_contract.docx");
        
        // 输出到响应流
        try (OutputStream outputStream = response.getOutputStream()) {
            document.write(outputStream);
        } finally {
            document.close();
        }
    }
    
    /**
     * 根据员工ID生成合同文档
     * 
     * @param employeeId 员工ID
     * @param response HTTP响应
     * @throws IOException IO异常
     */
    public void generateContractByEmployeeId(String employeeId, HttpServletResponse response) throws IOException {
        // 从后端服务获取员工数据
        ContractData contractData = contractDataService.getContractDataByEmployeeId(employeeId);
        
        // 创建合同模板文档
        XWPFDocument document = createContractTemplate();
        
        // 将合同数据转换为Map
        Map<String, String> dataMap = convertContractDataToMap(contractData);
        
        // 替换模板中的占位符
        replaceTextInDocument(document, dataMap);
        
        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.setHeader("Content-Disposition", 
            "attachment; filename=contract_" + contractData.getEmployeeName() + "_" + contractData.getContractNo() + ".docx");
        
        // 输出到响应流
        try (OutputStream outputStream = response.getOutputStream()) {
            document.write(outputStream);
        } finally {
            document.close();
        }
    }
    
    /**
     * 生成示例合同文档
     * 
     * @param response HTTP响应
     * @throws IOException IO异常
     */
    public void generateSampleContract(HttpServletResponse response) throws IOException {
        // 获取示例数据
        ContractData contractData = contractDataService.getSampleContractData();
        
        // 创建合同模板文档
        XWPFDocument document = createContractTemplate();
        
        // 将合同数据转换为Map
        Map<String, String> dataMap = convertContractDataToMap(contractData);
        
        // 替换模板中的占位符
        replaceTextInDocument(document, dataMap);
        
        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.setHeader("Content-Disposition", 
            "attachment; filename=sample_contract_" + contractData.getContractNo() + ".docx");
        
        // 输出到响应流
        try (OutputStream outputStream = response.getOutputStream()) {
            document.write(outputStream);
        } finally {
            document.close();
        }
    }
    
    /**
     * 替换文档中的文本
     * 
     * @param document Word文档
     * @param data 替换数据
     */
    private void replaceTextInDocument(XWPFDocument document, Map<String, String> data) {
        // 替换段落中的占位符
        replacePlaceholdersInParagraphs(document, data);
        
        // 替换表格中的占位符
        replacePlaceholdersInTables(document, data);
    }
    
    /**
     * 创建合同模板文档
     * 
     * @return Word文档对象
     */
    private XWPFDocument createContractTemplate() {
        XWPFDocument document = new XWPFDocument();
        
        // 创建标题
        XWPFParagraph titleParagraph = document.createParagraph();
        titleParagraph.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun titleRun = titleParagraph.createRun();
        titleRun.setText("劳动合同");
        titleRun.setBold(true);
        titleRun.setFontSize(18);
        
        // 添加空行
        document.createParagraph();
        
        // 合同编号和日期
        XWPFParagraph headerParagraph = document.createParagraph();
        XWPFRun headerRun = headerParagraph.createRun();
        headerRun.setText("合同编号：${contractNo}");
        headerRun.addTab();
        headerRun.addTab();
        headerRun.addTab();
        headerRun.setText("签订日期：${currentDate}");
        
        // 添加空行
        document.createParagraph();
        
        // 甲乙双方信息
        XWPFParagraph partyParagraph = document.createParagraph();
        XWPFRun partyRun = partyParagraph.createRun();
        partyRun.setText("甲方（用人单位）：${companyName}");
        partyRun.addBreak();
        partyRun.setText("法定代表人：${legalRepresentative}");
        partyRun.addBreak();
        partyRun.setText("公司地址：${companyAddress}");
        partyRun.addBreak();
        partyRun.addBreak();
        partyRun.setText("乙方（劳动者）：${employeeName}");
        partyRun.addBreak();
        partyRun.setText("身份证号：${idCard}");
        partyRun.addBreak();
        partyRun.setText("联系电话：${phone}");
        partyRun.addBreak();
        partyRun.setText("家庭住址：${address}");
        
        // 添加空行
        document.createParagraph();
        
        // 合同正文
        XWPFParagraph contentParagraph = document.createParagraph();
        XWPFRun contentRun = contentParagraph.createRun();
        contentRun.setText("根据《中华人民共和国劳动法》、《中华人民共和国劳动合同法》等相关法律法规，甲乙双方在平等自愿、协商一致的基础上，签订本劳动合同。");
        
        // 添加空行
        document.createParagraph();
        
        // 第一条：工作内容和工作地点
        XWPFParagraph article1 = document.createParagraph();
        XWPFRun article1Run = article1.createRun();
        article1Run.setText("第一条 工作内容和工作地点");
        article1Run.setBold(true);
        article1Run.addBreak();
        article1Run.setText("1.1 乙方同意根据甲方工作需要，担任${position}职务。");
        article1Run.addBreak();
        article1Run.setText("1.2 乙方工作地点：${workLocation}");
        
        // 第二条：合同期限
        XWPFParagraph article2 = document.createParagraph();
        XWPFRun article2Run = article2.createRun();
        article2Run.setText("第二条 合同期限");
        article2Run.setBold(true);
        article2Run.addBreak();
        article2Run.setText("2.1 本合同期限：${contractPeriod}");
        article2Run.addBreak();
        article2Run.setText("2.2 合同起始日期：${startDate}");
        article2Run.addBreak();
        article2Run.setText("2.3 合同终止日期：${endDate}");
        article2Run.addBreak();
        article2Run.setText("2.4 试用期：${probationPeriod}");
        
        // 第三条：工作时间和休息休假
        XWPFParagraph article3 = document.createParagraph();
        XWPFRun article3Run = article3.createRun();
        article3Run.setText("第三条 工作时间和休息休假");
        article3Run.setBold(true);
        article3Run.addBreak();
        article3Run.setText("3.1 工作时间：${workingHours}");
        
        // 第四条：劳动报酬
        XWPFParagraph article4 = document.createParagraph();
        XWPFRun article4Run = article4.createRun();
        article4Run.setText("第四条 劳动报酬");
        article4Run.setBold(true);
        article4Run.addBreak();
        article4Run.setText("4.1 乙方月工资：${salary}");
        article4Run.addBreak();
        article4Run.setText("4.2 工资发放时间：每月15日前发放上月工资");
        
        // 第五条：社会保险和福利待遇
        XWPFParagraph article5 = document.createParagraph();
        XWPFRun article5Run = article5.createRun();
        article5Run.setText("第五条 社会保险和福利待遇");
        article5Run.setBold(true);
        article5Run.addBreak();
        article5Run.setText("5.1 甲方为乙方提供的福利待遇：${benefits}");
        
        // 第六条：其他约定
        XWPFParagraph article6 = document.createParagraph();
        XWPFRun article6Run = article6.createRun();
        article6Run.setText("第六条 其他约定");
        article6Run.setBold(true);
        article6Run.addBreak();
        article6Run.setText("6.1 ${otherTerms}");
        
        // 添加空行
        document.createParagraph();
        
        // 签名区域
        XWPFParagraph signatureParagraph = document.createParagraph();
        XWPFRun signatureRun = signatureParagraph.createRun();
        signatureRun.setText("甲方（盖章）：");
        signatureRun.addTab();
        signatureRun.addTab();
        signatureRun.addTab();
        signatureRun.setText("乙方（签字）：");
        signatureRun.addBreak();
        signatureRun.addBreak();
        signatureRun.setText("日期：");
        signatureRun.addTab();
        signatureRun.addTab();
        signatureRun.addTab();
        signatureRun.addTab();
        signatureRun.setText("日期：");
        
        return document;
    }
    
    /**
     * 将合同数据转换为Map
     * 
     * @param contractData 合同数据对象
     * @return 数据Map
     */
    private Map<String, String> convertContractDataToMap(ContractData contractData) {
        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("companyName", contractData.getCompanyName() != null ? contractData.getCompanyName() : "");
        dataMap.put("employeeName", contractData.getEmployeeName() != null ? contractData.getEmployeeName() : "");
        dataMap.put("idCard", contractData.getIdCard() != null ? contractData.getIdCard() : "");
        dataMap.put("phone", contractData.getPhone() != null ? contractData.getPhone() : "");
        dataMap.put("contractNo", contractData.getContractNo() != null ? contractData.getContractNo() : "");
        dataMap.put("position", contractData.getPosition() != null ? contractData.getPosition() : "");
        dataMap.put("address", contractData.getAddress() != null ? contractData.getAddress() : "");
        dataMap.put("salary", contractData.getSalary() != null ? contractData.getSalary() : "");
        dataMap.put("startDate", contractData.getStartDate() != null ? contractData.getStartDate() : "");
        dataMap.put("endDate", contractData.getEndDate() != null ? contractData.getEndDate() : "");
        dataMap.put("currentDate", contractData.getCurrentDate() != null ? contractData.getCurrentDate() : "");
        dataMap.put("legalRepresentative", contractData.getLegalRepresentative() != null ? contractData.getLegalRepresentative() : "");
        dataMap.put("companyAddress", contractData.getCompanyAddress() != null ? contractData.getCompanyAddress() : "");
        dataMap.put("workLocation", contractData.getWorkLocation() != null ? contractData.getWorkLocation() : "");
        dataMap.put("contractPeriod", contractData.getContractPeriod() != null ? contractData.getContractPeriod() : "");
        dataMap.put("probationPeriod", contractData.getProbationPeriod() != null ? contractData.getProbationPeriod() : "");
        dataMap.put("workingHours", contractData.getWorkingHours() != null ? contractData.getWorkingHours() : "");
        dataMap.put("benefits", contractData.getBenefits() != null ? contractData.getBenefits() : "");
        dataMap.put("otherTerms", contractData.getOtherTerms() != null ? contractData.getOtherTerms() : "");
        return dataMap;
    }
    
    /**
     * 替换段落中的占位符
     * @param document Word文档对象
     * @param data 替换数据
     */
    private void replacePlaceholdersInParagraphs(XWPFDocument document, Map<String, String> data) {
        // 遍历所有段落
        for (XWPFParagraph paragraph : document.getParagraphs()) {
            // 获取段落文本
            String text = paragraph.getText();
            
            // 检查段落是否包含占位符
            boolean containsPlaceholder = false;
            for (String key : data.keySet()) {
                String placeholder = "${" + key + "}";
                if (text.contains(placeholder)) {
                    containsPlaceholder = true;
                    break;
                }
            }
            
            // 如果包含占位符，则进行替换
            if (containsPlaceholder) {
                // 获取段落中的所有文本运行
                List<XWPFRun> runs = paragraph.getRuns();
                
                // 如果有多个文本运行，需要合并处理
                if (runs.size() > 0) {
                    // 获取第一个运行的文本
                    String runText = runs.get(0).getText(0);
                    
                    // 如果有多个运行，合并它们
                    if (runs.size() > 1) {
                        for (int i = 1; i < runs.size(); i++) {
                            XWPFRun run = runs.get(i);
                            if (run.getText(0) != null) {
                                runText += run.getText(0);
                            }
                            // 清除当前运行的文本
                            run.setText("", 0);
                        }
                    }
                    
                    // 替换所有占位符
                    for (Map.Entry<String, String> entry : data.entrySet()) {
                        String placeholder = "${" + entry.getKey() + "}";
                        runText = runText.replace(placeholder, entry.getValue());
                    }
                    
                    // 将替换后的文本设置回第一个运行
                    runs.get(0).setText(runText, 0);
                }
            }
        }
    }
    
    /**
     * 替换表格中的占位符
     * @param document Word文档对象
     * @param data 替换数据
     */
    private void replacePlaceholdersInTables(XWPFDocument document, Map<String, String> data) {
        // 遍历所有表格
        for (XWPFTable table : document.getTables()) {
            // 遍历表格的所有行
            for (XWPFTableRow row : table.getRows()) {
                // 遍历行中的所有单元格
                for (XWPFTableCell cell : row.getTableCells()) {
                    // 遍历单元格中的所有段落
                    for (XWPFParagraph paragraph : cell.getParagraphs()) {
                        // 获取段落文本
                        String text = paragraph.getText();
                        
                        // 检查段落是否包含占位符
                        boolean containsPlaceholder = false;
                        for (String key : data.keySet()) {
                            String placeholder = "${" + key + "}";
                            if (text.contains(placeholder)) {
                                containsPlaceholder = true;
                                break;
                            }
                        }
                        
                        // 如果包含占位符，则进行替换
                        if (containsPlaceholder) {
                            // 获取段落中的所有文本运行
                            List<XWPFRun> runs = paragraph.getRuns();
                            
                            // 如果有多个文本运行，需要合并处理
                            if (runs.size() > 0) {
                                // 获取第一个运行的文本
                                String runText = runs.get(0).getText(0);
                                
                                // 如果有多个运行，合并它们
                                if (runs.size() > 1) {
                                    for (int i = 1; i < runs.size(); i++) {
                                        XWPFRun run = runs.get(i);
                                        if (run.getText(0) != null) {
                                            runText += run.getText(0);
                                        }
                                        // 清除当前运行的文本
                                        run.setText("", 0);
                                    }
                                }
                                
                                // 替换所有占位符
                                for (Map.Entry<String, String> entry : data.entrySet()) {
                                    String placeholder = "${" + entry.getKey() + "}";
                                    runText = runText.replace(placeholder, entry.getValue());
                                }
                                
                                // 将替换后的文本设置回第一个运行
                                runs.get(0).setText(runText, 0);
                            }
                        }
                    }
                }
            }
        }
    }
    
    /**
     * 批量处理合同模板
     * @param templatePath 模板文件路径
     * @param dataList 多组数据列表
     * @param outputDir 输出目录
     * @param fileNamePrefix 文件名前缀
     * @return 生成的文件路径列表
     * @throws IOException IO异常
     */
    public List<String> batchProcessContracts(String templatePath, List<Map<String, String>> dataList, 
                                            String outputDir, String fileNamePrefix) throws IOException {
        // 检查输出目录是否存在，不存在则创建
        File dir = new File(outputDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        
        // 存储生成的文件路径
        List<String> generatedFiles = new java.util.ArrayList<>();
        
        // 遍历数据列表，为每组数据生成一个合同文件
        for (int i = 0; i < dataList.size(); i++) {
            Map<String, String> data = dataList.get(i);
            
            // 读取模板文件
            File templateFile = new File(templatePath);
            FileInputStream fis = new FileInputStream(templateFile);
            XWPFDocument document = new XWPFDocument(fis);
            
            // 替换占位符
            replacePlaceholdersInParagraphs(document, data);
            replacePlaceholdersInTables(document, data);
            
            // 生成输出文件名
            String outputFileName = fileNamePrefix + "_" + (i + 1) + ".docx";
            String outputPath = outputDir + File.separator + outputFileName;
            
            // 写入文件
            FileOutputStream fos = new FileOutputStream(outputPath);
            document.write(fos);
            
            // 关闭资源
            fos.close();
            document.close();
            fis.close();
            
            // 添加到生成文件列表
            generatedFiles.add(outputPath);
        }
        
        return generatedFiles;
    }
}